package main

import (
	"fmt"
	"sync"
	"time"
)

// SyncTask 代表一个同步任务
type SyncTask struct {
	LinkId        string
	FullTableName string
	OpenLoadMode  bool
	OpenIncrement bool
}

// TaskQueue 是一个任务队列
type TaskQueue struct {
	tasks    []*SyncTask
	sem      chan struct{}
	lock     sync.Mutex
	capacity int
}

// NewTaskQueue 创建一个新的任务队列
func NewTaskQueue(capacity int) *TaskQueue {
	tq := &TaskQueue{
		tasks:    make([]*SyncTask, 0),
		sem:      make(chan struct{}, capacity),
		capacity: capacity,
	}
	// 每隔5秒打印任务运行状态
	go func() {
		t := time.Now()
		for {
			if time.Since(t) > time.Second*5 && len(tq.sem) > 0 || len(tq.tasks) > 0 {
				fmt.Printf("正在运行的任务: %d, 等待中的任务: %d\n", len(tq.sem), len(tq.tasks))
				t = time.Now()
			}
		}
	}()
	return tq
}

// AddTask 添加任务到队列中
func (tq *TaskQueue) AddTask(task *SyncTask) {
	tq.lock.Lock()
	defer tq.lock.Unlock()
	for _, t := range tq.tasks {
		if t.LinkId == task.LinkId && t.FullTableName == task.FullTableName &&
			t.OpenLoadMode == task.OpenLoadMode && t.OpenIncrement == task.OpenIncrement {
			return
		}
	}
	tq.tasks = append(tq.tasks, task)
}

// CancelTask 从队列中取消任务
func (tq *TaskQueue) CancelTask(task *SyncTask) {
	tq.lock.Lock()
	defer tq.lock.Unlock()
	for i, t := range tq.tasks {
		if t.LinkId == task.LinkId && t.FullTableName == task.FullTableName {
			tq.tasks = append(tq.tasks[:i], tq.tasks[i+1:]...)
			break
		}
	}
}

// GetTaskAndRun 从队列中获取任务并执行
func (tq *TaskQueue) GetTaskAndRun() {
	tq.lock.Lock()
	if len(tq.tasks) == 0 {
		tq.lock.Unlock()
		return
	}
	task := tq.tasks[0]
	tq.tasks = tq.tasks[1:]
	tq.lock.Unlock()

	tq.sem <- struct{}{}
	go func() {
		defer func() {
			<-tq.sem
		}()
		tq.RunFullSyncTask(*task)
	}()
}

// RunFullSyncTask 执行同步任务
func (tq *TaskQueue) RunFullSyncTask(task SyncTask) {
	// 执行 Task
	// 可以添加错误处理逻辑
	time.Sleep(1 * time.Second)
	// 示例：打印任务信息
	println("Executing task:", task.LinkId, task.FullTableName)
}

func main() {
	taskQueue := NewTaskQueue(3)

	// 获取任务并执行
	go func() {
		for {
			taskQueue.GetTaskAndRun()
			time.Sleep(time.Microsecond * 100)
		}
	}()

	// 模拟 往里面添加任务 真实场景是用户在页面点击
	go func() {
		for i := 0; i < 5; i++ {
			task := &SyncTask{
				LinkId:        "123",
				FullTableName: "test",
				OpenLoadMode:  true,
				OpenIncrement: true,
			}
			taskQueue.AddTask(task)
		}
	}()

	// 模拟 取消任务
	go func() {
		for {
			if len(taskQueue.tasks) > 0 {
				task := &SyncTask{
					LinkId:        "123",
					FullTableName: "test",
					OpenLoadMode:  true,
					OpenIncrement: true,
				}
				taskQueue.CancelTask(task)
			}
			time.Sleep(time.Second)
		}
	}()

	// 防止主函数提前退出
	select {}
}
